<?php
namespace app\common\controller;

use app\admin\model\File;
use app\admin\model\FileType;
use app\admin\model\Pic;
use app\admin\model\PicType;
use OSS\Core\OssException;
use OSS\OssClient;
use think\facade\Env;

/**
 * Class AliyunUpload
 * @package app\common\controller
 *
 * DROP TABLE IF EXISTS `pic_type`;
CREATE TABLE `pic_type` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name_full` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '图片类型名称',
`bucket_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '阿里云bucket名称',
`finder_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '阿里云的样式名称',
`pic_url` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '图片的域名',
`ext` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '图片的后缀',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

-- ----------------------------
-- Records of pic_type
-- ----------------------------
INSERT INTO `pic_type` VALUES ('1', '用户头像', 'haimo', 'face', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('2', 'appbanner', 'haimo', 'banner', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('3', '圈子照片', 'haimo', 'circle', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('4', '资源图片', 'haimo', 'resource', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('6', '运营位icon', 'haimo', 'yywindex', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('7', '资源资质图片', 'haimo', 'resource_zizhi', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('8', '策划案logo', 'haimo', 'planlogo', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('9', '策划案展示图', 'haimo', 'planshow', 'http://haimo.iwawo.com/', '.jpg');
INSERT INTO `pic_type` VALUES ('10', '猫窝图片', 'haimo', 'shop', 'http://haimo.iwawo.com/', '.jpg');
 *
DROP TABLE IF EXISTS `file_type`;
CREATE TABLE `file_type` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name_full` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '图片类型名称',
`finder_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '服务器存储附件的文件夹名称 %Y-%m-%d 将被解析成对应的时间',
`is_zip` tinyint(4) unsigned DEFAULT '0' COMMENT '如果是zip打包文件 则会存放到文件服务器中，通过邮件方式发送给用户。其它放入本地',
`host` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '附件所在服务器',
`pinyin` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '' COMMENT '类型的拼音',
`ext` varchar(11) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
`template_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

-- ----------------------------
-- Records of file_type
-- ----------------------------
INSERT INTO `file_type` VALUES ('1', '视频文件', 'resource-video%Ym%', '0', '', '', '.mp4', 'S00000001-200010');
INSERT INTO `file_type` VALUES ('2', '音频文件', 'mp3%Ym%', '0', '', '', '.mp3', 'S00000001-300020');
INSERT INTO `file_type` VALUES ('3', 'ppt文件', 'ppt%Ym%', '0', '', '', '.ppt', 'S00000001-300030');
INSERT INTO `file_type` VALUES ('4', 'pdf文件', 'pdf%Ym%', '0', '', '', '.pdf', 'S00000001-300040');
INSERT INTO `file_type` VALUES ('5', 'pptx文件', 'pptx%Ym%', '0', '', '', '.pptx', 'S00000001-300050');
INSERT INTO `file_type` VALUES ('6', '文件', 'file%Ym%', '0', '', '', '', '');

 */
class AliyunUpload {
    private $client = null;
    private $appid;
    private $secret;
    private $endpoint;
    private $file_type;
    private $bucketName;
    /**
     * AliyunUpload constructor.
     * @param int $type_id
     * @param string $file_type
     * @throws OssException
     */
    public function __construct($type_id = 4,$file_type='pic'){
        $this->appid = Env::get('ALIYUN.ALIYUN_ACCESS_KEY_ID');
        $this->secret = Env::get('ALIYUN.ALIYUN_ACCESS_KEY_SECRET');
        $this->endpoint = Env::get('ALIYUN.ALIYUN_ENDPOINT');
        $this->client = new OssClient($this->appid,$this->secret,$this->endpoint);
        $this->bucketName = $this->picurl = $this->finder = $this->ext = $this->type_id = $this->template_id = '';
        $this->file_type = $file_type;
        if($file_type == 'pic'){
            //获取pic_type对应的参数
            $PicType = new PicType();
            $type_detail = $PicType->getById($type_id);
            if(empty($type_detail)){
                return false;
            }
            $this->bucketName = $type_detail['bucket_name'];
            $this->picurl = $type_detail['pic_url']; //图片域名
            $this->finder = $type_detail['finder_name']; //图片的文件夹名称
            $this->ext = $type_detail['ext']; //图片后缀
            $this->type_id = $type_id;
        }
        if($file_type == 'video'){
            //上传文件待完善
            $FileType = new FileType();
            $type_detail = $FileType->getById($type_id);
            $this->finder = $type_detail['finder_name']; //图片的文件夹名称
            $this->ext = $type_detail['ext']; //图片后缀
            $this->template_id = $type_detail['template_id'];
            $this->type_id = $type_id;
        }
    }

    /**
     * @param string $file
     * @param array $out
     * @return null
     */
    public function upload_image($file='image',&$out=[]){
        try {
            $info = request()->file($file)->getInfo();
            //这里是有sha1加密 生成文件名 之后连接上后缀
            $fileName = $this->finder.'/'.$this->setPicName() .$this->ext; //生成图片名称
            //执行阿里云上传
            $result = $this->client->uploadFile('haimo',$fileName,$info['tmp_name']);
            $pic = new Pic();
            $id = $pic->addPic($result['info']['url'],$this->type_id);
            $out = ['status'=>1,'data'=>['pic_ids'=>$id,'pic_images'=>$result['info']['url']]];
            return $id;
        } catch (OssException $e) {
          $out = ['status'=>0,'path'=>$e->getMessage()];
          return false;
        }
    }

    /**
     * 上传文件
     * @param string $file
     * @param array $out
     * @return bool
     */
    public function upload_file($file='file',&$out=[]){
        try {
            $info = request()->file($file)->getInfo();
            //这里是有sha1加密 生成文件名 之后连接上后缀
            $fileName = $this->finder.'/'.$this->setPicName() .$this->ext; //生成图片名称
            //执行阿里云上传
            $result = $this->client->uploadFile('haimo',$fileName,$info['tmp_name']);
            $pic = new Pic();
            $id = $pic->addPic($result['info']['url'],$this->type_id);
            $out = ['status'=>1,'data'=>['pic_ids'=>$id,'file_pat'=>$result['info']['url']]];
            return $id;
        } catch (OssException $e) {
            $out = ['status'=>0,'path'=>$e->getMessage()];
            return false;
        }
    }

    /**
     * 上传图片
     * @param string $file
     * @param int $type
     * @param int $new_id
     * @return array
     */
    public function uploads($file="file",$type=0,&$new_id=0){
        if($type){
            if($this->file_type == 'pic') {
                $PicType = new PicType();
                $type_detail = $PicType->getById($type);
            }else{
                $FileType = new FileType();
                $type_detail = $FileType->getById($type);
                $this->template_id = $type_detail['template_id'];
            }
            $this->bucketName = $type_detail['bucket_name'];
            $this->picurl = $type_detail['pic_url']; //图片域名
            $this->finder = $type_detail['finder_name']; //图片的文件夹名称
            $this->ext = $type_detail['ext']; //图片后缀
            $this->type_id = $type;
        }
        try {
            $info = request()->file($file)->getInfo();
            //这里是有sha1加密 生成文件名 之后连接上后缀
            $fileName = $this->finder.'/'.$this->setPicName() .$this->ext; //生成图片名称
            //执行阿里云上传
            $result = $this->client->uploadFile('haimo',$fileName,$info['tmp_name']);
            $pic = new Pic();
            $id = $pic->addPic($result['info']['url'],$this->type_id);
            $new_id = $id;
            return ['status'=>1,'data'=>['pic_id'=>$id,'pic_image'=>$result['info']['url']]];
        } catch (OssException $e) {
            return ['status'=>0,'path'=>$e->getMessage()];
        }
    }

    /**
     * @param string $file
     * @throws OssException
     */
    public function uploadUeditor($file="upfile"){
        $result = ['state'=>'no create'];
        $action = $_GET['action'];
        if($action == 'config'){
            $CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents("./static/config.json")), true);
            $result =  json_encode($CONFIG);
        }
        $_file = $_FILES[$file];
        $ext = '.' . end(explode('.',$_file['name']));
        $arr = array(
            'state'=>'SUCCESS',
            'original'=>$_file['name'],
            'type'=>$ext,
            'size'=>$_file['size']
        );
        $fileName = $this->finder.'/'.$this->setPicName() .$this->ext;
        if ($action == 'uploadimage') {
            $res = $this->client->uploadFile($this->bucketName,$fileName,$_file['tmp_name']);
            if($result){
                $arr['url']=$res['info']['url'];
                $arr['title']=$fileName;
                $result = json_encode($arr);
            }else{
                $arr['state']='error';
                $result = json_encode($arr);
            }
        }
        if ($action == 'uploadvideo') {
            $res = $this->client->uploadFile($this->bucketName,$fileName,$_file['tmp_name']);
            if($result){
                $arr['url']=$res['info']['url'];
                $arr['title']=$fileName;
                $result = json_encode($arr);
            }else{
                $arr['state']='error';
                $result = json_encode($arr);
            }
        }

        if ($action == 'uploadfile') {
            $res = $this->client->uploadFile($this->bucketName,$fileName,$_file['tmp_name']);
            if($result){
                $arr['url']=$res['info']['url'];
                $arr['title']=$fileName;
                $result = json_encode($arr);
            }else{
                $arr['state']='error';
                $result = json_encode($arr);
            }
        }

        if($action = 'listimage') {
            $res = $this->getFileListByDir('circle');
            if($res['status']){
                $arr = [
                    "state" => "SUCCESS",
                    "list" => $res['list'],
                    "start" => 0,
                    "total" => count($res['list'])
                ];
                $result =  json_encode($arr);
            }else{
                $arr = [
                    "state" => "no match file",
                    "list" => array(),
                    "start" => 0,
                    "total" => 0
                ];
                $result =  json_encode($arr);
            }
        }

        if($action == 'listfile'){
            $res = $this->getFileListByDir('file');
            if($res['status']){
                $arr = [
                    "state" => "SUCCESS",
                    "list" => $res['list'],
                    "start" => 0,
                    "total" => count($res['list'])
                ];
                $result =  json_encode($arr);
            }else{
                $arr = [
                    "state" => "no match file",
                    "list" => array(),
                    "start" => 0,
                    "total" => 0
                ];
                $result =  json_encode($arr);
            }
        }

        /* 输出结果 */
        if (isset($_GET["callback"])) {
            if (preg_match("/^[\w_]+$/", $_GET["callback"])) {
                echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
            } else {
                echo json_encode(['state'=> 'callback参数不合法']);
            }
        } else {
            echo json_encode($result);
        }
    }

    /**
     * @param string $dir
     * @param string $delimiter
     * @param string $bucket
     * @param string $nextMarker
     * @param int $maxkeys
     * @return array
     */
    public function getFileListByDir($dir='dir/',$delimiter='/',$bucket='', $nextMarker='',$maxkeys=10){
        $bucket = $bucket?$bucket:$this->bucketName;
        $options = array(
            'delimiter' => $delimiter,
            'prefix' => $dir,
            'max-keys' => $maxkeys,
            'marker' => $nextMarker,
        );
        try {
            $listObjectInfo = $this->client->listObjects($bucket, $options);
        } catch (OssException $e) {
            return ['status'=>0,'msg'=>$e->getMessage()];
        }
        $list = $prefixList = [];
        $objectList = $listObjectInfo->getObjectList(); // object list
        $prefixList = $listObjectInfo->getPrefixList(); // directory list
        if (!empty($objectList)) {
            foreach ($objectList as $objectInfo) {
                array_push($list,[
                    'Key'=>$objectInfo->getKey(),
                    'ETag'=>$objectInfo->getETag(),
                    'storage'=>$objectInfo->getStorageClass(),
                    'size'=>$objectInfo->getSize()
                ]);
            }
        }
        if (!empty($prefixList)) {
            foreach ($prefixList as $prefixInfo) {
                array_push($prefixList,['prefix'=>$prefixInfo->getPrefix()]);
            }
        }
        return ['status'=>1,'list'=>$list,'prefix'=>$prefixList];
    }
    /**
     * @param string $bucket
     * @return array
     */
    public function getAllFileList($bucket=''){
        $bucket = $bucket?$bucket:$this->bucketName;
        $list = $prefixList = [];
        while (true) {
            try {
                $listObjectInfo = $this->client->listObjects($bucket);
            } catch (OssException $e) {
                return ['status'=>0,'msg'=>$e->getMessage()];
            }
            // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表。
            $nextMarker = $listObjectInfo->getNextMarker();
            $listObject = $listObjectInfo->getObjectList();
            $listPrefix = $listObjectInfo->getPrefixList();

            if (!empty($listObject)) {
                foreach ($listObject as $objectInfo) {
                    array_push($list,[
                        'Key'=>$objectInfo->getKey(),
                        'ETag'=>$objectInfo->getETag(),
                        'storage'=>$objectInfo->getStorageClass(),
                        'size'=>$objectInfo->getSize()
                    ]);
                }
            }
            if (!empty($listPrefix)) {
                print("prefixList: \n");
                foreach ($listPrefix as $prefixInfo) {
                    array_push($prefixList,['prefix'=>$prefixInfo->getPrefix()]);
                }
            }
            if ($nextMarker === '') {
                break;
            }
        }
        return ['status'=>1,'list'=>$list,'prefix'=>$prefixList];
    }

    /**
     * @param int $type
     */
    public function get_websin(){
        $type = input('type');
        if($type==1){
            $dir = 'resource-video-old/';
        }elseif($type == 11){
            //文件上传
            $dir = 'plan_case/';
        }elseif($type == 10){
            //消息回复
            $dir = 'customer_msg/';
        }elseif($type == 7){
            //消息回复
            $dir = 'resource_zizhi/';
        }else{
            $dir = 'resource/';
        }
        $id= $this->appid;          // 请填写您的AccessKeyId。
        $key= $this->secret;     // 请填写您的AccessKeySecret。
        // $host的格式为 bucketname.endpoint，请替换为您的真实信息。
        $host = Env::get('ALIYUN.ALIYUN_HOST','http://haimo.oss-cn-hangzhou.aliyuncs.com');
        // $callbackUrl为上传回调服务器的URL，请将下面的IP和Port配置为您自己的真实URL信息。
        $callbackUrl = Env::get('ALIYUN.CALLBACK_URL','http://storev5api.iwawo.com/index/index/callback');
        $callback_param = array(
            'callbackUrl'=>$callbackUrl,
            'callbackBody'=>'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}&type_id='.$this->type_id,
            'callbackBodyType'=>"application/x-www-form-urlencoded"
        );
        $callback_string = json_encode($callback_param);

        $base64_callback_body = base64_encode($callback_string);
        $now = time();
        $expire = 60;  //设置该policy超时时间是10s. 即这个policy过了这个有效时间，将不能访问。
        $end = $now + $expire;
        $expiration = gmt_iso8601($end);

        //最大文件大小.用户可以自己设置
        $condition = array(0=>'content-length-range', 1=>0, 2=>1048576000);
        $conditions[] = $condition;

        // 表示用户上传的数据，必须是以$dir开始，不然上传会失败，这一步不是必须项，只是为了安全起见，防止用户通过policy上传到别人的目录。
        $start = array(0=>'starts-with', 1=>'$key', 2=>$dir);
        $conditions[] = $start;

        $arr = array('expiration'=>$expiration,'conditions'=>$conditions);
        $policy = json_encode($arr);
        $base64_policy = base64_encode($policy);
        $string_to_sign = $base64_policy;
        $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));
        $name = $this->finder.'-'.date('YmdHis',time());
        $response = array();
        $response['accessid'] = $id;
        $response['host'] = $host;
        $response['policy'] = $base64_policy;
        $response['signature'] = $signature;
        $response['expire'] = $end;
        $response['callback'] = $base64_callback_body;
        $response['dir'] = $dir.$name.'-'.'${filename}';
        echo json_encode($response);
    }

    /**
     * @param $del_obj
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function delete($del_obj){
        if($this->file_type=='pic'){
            $obj = (new Pic())->where('id|picurl','eq',$del_obj)->find();
            if($obj){
                return $this->client->deleteObject($this->bucketName,$obj['picurl']);
            }else{
                return ['status'=>0,'msg'=>'图片不存在'];
            }
        }else{
            $obj = (new File())->where('id|picurl','eq',$del_obj)->find();
            if($obj){
                return $this->client->deleteObject($this->bucketName,$obj['picurl']);
            }else{
                return ['status'=>0,'msg'=>'图片不存在'];
            }
        }
    }


    //名称生成
    private function setPicName(){
        $name='dav';
        $typeData = $this->getTypeFinder($this->finder);
        if(is_array($typeData)){
            $typeData = implode('', $typeData);
            $t1='';
        }else{
            $t1=date('ymdHis');
        }
        $name .= '-'.$typeData;
        $micr = explode(".", microtime(true));
        $name .= $t1.rand(0, 9).$micr[1];
        return $name;
    }

    private function getTypeFinder(){
        $typeData = $this->finder;
        if(stripos($typeData,'%Ym%')>0){
            $typeDatas = str_replace('%Ym%','/'.date('Ym'), $typeData);
            $typeData = explode('/', $typeDatas);
        }
        return $typeData;
    }
}